﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace IFT.Classes
{
  #region BattlefieldEnums
  public enum BattlefieldType
  {
    MinBattlefieldType,
    Village,
    Town,
    Metropolis,
    Sea,
    MaxBattlefieldType
  }
  #endregion BattlefieldEnums

  class Battlefield
  {
    private Player m_attacker       = null;
    private Player m_defender       = null;
    private BattlefieldType m_type  = BattlefieldType.MinBattlefieldType;

    #region BattlefieldPropertys
    public Player Attacker
    {
      get { return m_attacker; }
    }

    public Player Defender
    {
      get { return m_defender; }
    }

    public BattlefieldType Type
    {
      get { return m_type; }
    }
    #endregion BattlefieldPropertys

    public Battlefield() { }

    public Battlefield(BattlefieldType BfType)
    {
      m_type = BfType;
      m_attacker = new Player(this);
      m_defender = new Player(this);
      Attacker.Role = PlayerRole.RoleAttacker;
      Defender.Role = PlayerRole.RoleDefender;
    }

    public int GetMaxSlots(UnitType UType)
    {
      int[] maxSlots;

      switch (Type)
      {
        case BattlefieldType.Village:
          {
            maxSlots = new int[(int)UnitType.MaxUnitFieldType - 1] { 3, 0, 3, 1, 1, 1, 2 };
          } break;
        case BattlefieldType.Town:
          {
            maxSlots = new int[(int)UnitType.MaxUnitFieldType - 1] { 5, 2, 5, 2, 1, 1, 2 };
          } break;
        case BattlefieldType.Metropolis:
          {
            maxSlots = new int[(int)UnitType.MaxUnitFieldType - 1] { 7, 4, 7, 3, 1, 1, 2 };
          } break;
        case BattlefieldType.Sea:
          {
            maxSlots = new int[(int)UnitType.MaxUnitFieldType - 1] { 5, 0, 5, 0, 0, 1, 0 };
          } break;
        default:
          {
            maxSlots = new int[(int)UnitType.MaxUnitFieldType - 1] { 0, 0, 0, 0, 0, 0, 0 };
          } break;
      }

      return maxSlots[(int)UType - 1];
    }

    public UnitType[] GetFiringSequence()
    {
      UnitType[] order = new UnitType[6] { UnitType.AirDefense, UnitType.Bomber, UnitType.Artillery, UnitType.LongRange, UnitType.HeavyInfantry, UnitType.LightInfantry };
      return order;
    }

    public CombatLine[] GetFiringLines()
    {
      UnitType[] firingSequence = GetFiringSequence();
      CombatLine[] combatFields = new CombatLine[6];

      for (int i = 0; i < 6; i++)
        combatFields[i] = Attacker.GetField(firingSequence[i]);

      return combatFields;
    }

    public UnitType[] GetAttackSequence(UnitType UType)
    {
      UnitType[] attackSequence;

      switch (UType)
      {
        case UnitType.HeavyInfantry:
          {
            attackSequence = new UnitType[(int)UnitType.MaxUnitFieldType - 1] { UnitType.HeavyInfantry, UnitType.LongRange, UnitType.Artillery, UnitType.LightInfantry, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType };
          } break;
        case UnitType.LightInfantry:
          {
            attackSequence = new UnitType[(int)UnitType.MaxUnitFieldType - 1] { UnitType.LightInfantry, UnitType.LongRange, UnitType.Artillery, UnitType.HeavyInfantry, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType };
          } break;
        case UnitType.LongRange:
          {
            attackSequence = new UnitType[(int)UnitType.MaxUnitFieldType - 1] { UnitType.HeavyInfantry, UnitType.LightInfantry, UnitType.LongRange, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType };
          } break;
        case UnitType.Artillery:
          {
            attackSequence = new UnitType[(int)UnitType.MaxUnitFieldType - 1] { UnitType.HeavyInfantry, UnitType.LightInfantry, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType };
          } break;
        case UnitType.AirDefense:
          {
            attackSequence = new UnitType[(int)UnitType.MaxUnitFieldType - 1] { UnitType.Bomber, UnitType.AirDefense, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType };
          } break;
        case UnitType.Bomber:
          {
            attackSequence = new UnitType[(int)UnitType.MaxUnitFieldType - 1] { UnitType.Artillery, UnitType.LongRange, UnitType.HeavyInfantry, UnitType.LightInfantry, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType };
          } break;
        default:
          {
            attackSequence = new UnitType[(int)UnitType.MaxUnitFieldType - 1] { UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType, UnitType.MinUnitFieldType };
          } break;
      }

      return attackSequence;
    }

    public CombatLine[] GetAttackLines(UnitType UType)
    {
      UnitType[] attackSequence = GetAttackSequence(UType);
      CombatLine[] combatFields = new CombatLine[(int)UnitType.MaxUnitFieldType - 1];

      for (int i = (int)UnitType.MinUnitFieldType; i < (int)UnitType.MaxUnitFieldType; i++)
      {
        if (attackSequence[i] != UnitType.MinUnitFieldType) 
          combatFields[i] = Defender.GetField(attackSequence[i]);
      }

      return combatFields;
    }

    public void DoAttack()
    {
      CombatLine[] attackSequence = null;
      CombatLine[] firingOrder = GetFiringLines();
      bool unitDidHit = false;

      foreach (CombatLine attackerField in firingOrder)
      {
        attackSequence = GetAttackLines(attackerField.Type);

        foreach (Unit attackerUnit in attackerField)
        {
          if (!attackerUnit.IsAlive())
            continue;

          foreach (CombatLine defenderField in attackSequence)
          {
            foreach (Unit defenderUnit in defenderField)
            {
              if (!defenderUnit.IsAlive())
                continue;

              defenderUnit.RecieveDamage(attackerUnit);
              attackerUnit.RecieveDamage(defenderUnit);
              defenderUnit.EndRound();
              attackerUnit.EndRound();
              unitDidHit = true;
              break;
            }

            if (unitDidHit)
              break;
          }
        }
      }
    } 

    public void NextRound()
    {
      Attacker.FillAllFieldLines();
      Defender.FillAllFieldLines();
      DoAttack();
      //Fix me: Unit Heal, Moral changes a.s.o.
    }

    public String GetCombatLog()
    {
      String combatMsg = "";
      //UnitDamage damage = null;
      //CombatLine combatLine = null;

      combatMsg += "Verteidiger:\n";

      /*for (UnitType i = UnitType.MinUnitFieldType + 1; i < UnitType.MaxUnitFieldType; i++)
      {
        combatLine = m_defender.GetField(i);
        damage = combatLine.GetLog();
        combatMsg += String.Format("erleidet {0} Schaden durch {1}\n", damage.DamageRecieved);
      }*/

      return combatMsg;
    }
  }
}
